<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <h1>网址：</h1>
    <h1>https://juejin.im/post/5bde7c926fb9a049f66b8b52#heading-2</h1>
    <script>

        /**
         * 模拟实现 new 操作符
         * @param  {Function} ctor [构造函数]
         * @return {Object|Function|Regex|Date|Error}      [返回结果]
         */
        function newOperator(ctor) {
            if (typeof ctor !== 'function') {
                throw 'newOperator function the first param must be a function';
            }

            // ES6 new.target 是指向构造函数
            newOperator.target = ctor;

            // 1、创建一个全新的对象
            // 2、并且执行【Prototype】链接
            // 3、通过`new`创建的每个对象将最终被`[[Prototype]]`链接到这个函数的`prototype`对象上。
            let newObj = Object.create(ctor.prototype);

            // ES5 arguments转成数组 当然也可以用ES6 [...arguments], Aarry.from(arguments);
            // 除去ctor构造函数的其余参数
            let argsArr = [].slice.call(arguments, 1);

            // 3.生成的新对象会绑定到函数调用的`this`。
            // 获取到ctor函数返回结果
            var ctorReturnResult = ctor.apply(newObj, argsArr);


            // 小结4 中这些类型中合并起来只有Object和Function两种类型 typeof null 也是'object'所以要不等于null，排除null
            var isObject = typeof ctorReturnResult === 'object' && ctorReturnResult !== null;
            var isFunction = typeof ctorReturnResult === 'function';
            if (isObject || isFunction) {
                return ctorReturnResult;
            }


            // 5.如果函数没有返回对象类型`Object`(包含`Functoin`, `Array`, `Date`, `RegExg`, `Error`)，那么`new`表达式中的函数调用会自动返回这个新的对象。
            return newObj;

        }




        function fn() {
            // 1、先默认创建一个对象
            // 2、让obj的__proto__指向fn的prototype
            // 3、让当前作用域下的this指向该对象
            // 4、返回这个对象
            this.num = 100
        }

        let f = new fn
        let f2 = new fn

        console.log(f === f2);// 空间地址不同
        console.log(f);

        // 面向对象 类的继承 封装 多态
        // f 是 fn 的一个实例  fn 是一个自定义类
        
        // instanceOf 检测当前实例是否属于某个类方法 
        console.log(f instanceof fn);


    </script>
</body>

</html>